package xperiment.metaphor.model.entity;

import java.io.Serializable;
import java.util.List;
import xperiment.metaphor.model.*;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import metaphor.service.ServiceException;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
import metaphor.persistence.filter.Query;
import metaphor.persistence.filter.SimpleExpression;

/**
 * Contact type
 *
 * @author Mark Ashworth
 * @version 1.0.0
 * @since 1.0.0
 */
@Entity
@Table(name="gender")
public class ContactType extends DomainObject implements Persistent, Named, Comparable {

    @Id @GeneratedValue(strategy=GenerationType.AUTO) 
    @Column(name = "contact_type_id", unique = true, nullable = false)
    private Serializable id = null;
    
    /* The name of the contact type */
    @Column(name = "contact_type_name", unique = true, nullable = false, length=10)
    private String name;
    
    /* Whether the object is enabled */
    @Column(name = "enabled", nullable = false)
    private boolean enabled = true;

    /** Personal contact type */
    public static final ContactType PERSONAL = new ContactType("PERSONAL");

    /** Business contact type */
    public static final ContactType BUSINESS = new ContactType("BUSINESS");

    /** Other contact type */
    public static final ContactType OTHER = new ContactType("OTHER");

    /**
     * Default constructor
     */
	public ContactType() {
		this(null);
	}
	
    /**
     * Constructs the contact type with it's name
     * @param name The contact type name
     */
	public ContactType(String name) {
		super();
        this.name = name;
	}
	
    /**
     * The unique id of the object
     * @return Long
     */
	@Override
    public Serializable getId() {
		return this.id;
	}

    /**
     * The name of the gender
     * @return String
     */
	@Override 
    public String getName() {
		return this.name;
	}

    /**
     * Whether the gender is enabled
     * @return boolean
     */
    public boolean isEnabled() {
        return this.enabled;
    }
    
    /**
     * Returns the gender name as the String representation
     * @return String
     */
    @Override
    public String toString() {
        return getName();
    }
    
    /**
     * &lt;gender class="xperiment.metaphor.model.people.Gender" name="MALE"/&gt;
     * @return String
     */
    public String toXML() {
        return "<contact-type class='" + getClass().getName()
                + "' id='" + getId() 
                + "' name='" + getName() 
                + "' enabled='" + isEnabled() 
                + "' />";
    }

    /**
     * Saves the gender if not already present in the persistent store
     */
    public ContactType save() throws SaveException {

        /*
         * Persist the gender
         */
        try {
            List values = getDao().retrieve(Query.forClass(ContactType.class).add(SimpleExpression.ilike("name", getName())));
            if (values != null && values.size() == 1) {
                ContactType g = (ContactType) values.get(0);
                this.id = g.getId();
            } else if (values != null && values.size() == 0) {
                ContactType g = (ContactType) getDao().persist(this);
                this.id = g.getId();
            } else if (values != null && values.size() > 1) {
                throw new SaveException("Multiple contact types found for name " + getName());
            } else {
                throw new SaveException("Null values returned from retrieve query");
            }
            return this;
        } catch (ServiceException e) {
            throw new SaveException("Unable to save contact type", e);
        }
    }

    /**
     * Calculates comparison based upon the name of the contact type
     * @param obj The other object
     * @return boolean
     */
    @Override
    public int compareTo(Object o) {
        ContactType rhs = (ContactType) o;
        return new CompareToBuilder()
                .append(getName(), rhs.getName())
                .toComparison();
    }

    /**
     * Calculates equality based upon the name of the contact type
     * @param obj The other object
     * @return boolean
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null) { return false; }
        if (obj == this) { return true; }
        if (obj.getClass() != getClass()) {
          return false;
        }
        ContactType rhs = (ContactType) obj;

        return new EqualsBuilder()
                .append(getName(), rhs.getName())
                .isEquals();
    }

    /**
     * Calculates the hash code based upon the name of the contact type
     * @return int
     */
    @Override
    public int hashCode() {
        int hash = 5;
        hash = 59 * hash + (this.name != null ? this.name.hashCode() : 0);
        return hash;
    }
}
